package com.hellobike.haxing.modules.product.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.hellobike.haxing.common.vo.ProductResultCode;
import com.hellobike.haxing.common.vo.Result;
import com.hellobike.haxing.modules.product.entity.Product;
import com.hellobike.haxing.modules.product.entity.Promotion;
import com.hellobike.haxing.modules.product.entity.PromotionGroup;
import com.hellobike.haxing.modules.product.entity.PromotionGroupSku;
import com.hellobike.haxing.modules.product.mapper.ProductMapper;
import com.hellobike.haxing.modules.product.mapper.PromotionGroupMapper;
import com.hellobike.haxing.modules.product.mapper.PromotionGroupSkuMapper;
import com.hellobike.haxing.modules.product.mapper.PromotionMapper;
import com.hellobike.haxing.modules.product.model.PromotionGroupNoJoin;
import com.hellobike.haxing.modules.product.model.PromotionGroupNojoinSku;
import com.hellobike.haxing.modules.product.service.IPromotionGroupService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @Description: 拼团商品
 * @Author: haxing-boot
 * @Date: 2020-01-29
 * @Version: V1.0
 */
@Service
public class PromotionGroupServiceImpl extends ServiceImpl<PromotionGroupMapper, PromotionGroup> implements IPromotionGroupService {

    @Autowired
    private PromotionGroupMapper promotionGroupMapper;
    @Autowired
    private PromotionGroupSkuMapper promotionGroupSkuMapper;
    @Autowired
    private PromotionMapper promotionMapper;
    @Autowired
    private ProductMapper productMapper;

    @Override
    public IPage<PromotionGroup> page(Page<PromotionGroup> page, QueryWrapper<PromotionGroup> queryWrapper) {
        IPage<PromotionGroup> pageList = promotionGroupMapper.selectPage(page, queryWrapper);
        fillProductInfo(pageList.getRecords());

        return pageList;
    }

    /**
     * 填充商品信息
     *
     * @param promotionGroupList
     */
    private void fillProductInfo(List<PromotionGroup> promotionGroupList) {
        if (promotionGroupList != null && promotionGroupList.size() > 0) {
            List<Long> productIdList = promotionGroupList.stream().map(PromotionGroup::getProductId).distinct().collect(Collectors.toList());
            List<Product> productList = productMapper.selectBatchIds(productIdList);
            Map<Long, Product> productMap = productList.stream().collect(Collectors.toMap(Product::getId, Function.identity()));
            promotionGroupList.forEach(promotionGroup -> {
                Product product = productMap.get(promotionGroup.getProductId());
                if (product == null) return;
                promotionGroup.setProductName(product.getTitle());
                promotionGroup.setSpuCode(product.getSpuCode());
            });
        }
    }

    //判断商品参加的活动时间是否重叠
    public boolean isProductPromotionTimeConflict(PromotionGroup promotionGroup) {
        List<Promotion> productPromotions = promotionMapper.getProductPromotions(promotionGroup.getProductId());
        if (productPromotions.size() > 0) {
            Promotion promotion = promotionMapper.selectById(promotionGroup.getPromotionId());
            for (Promotion otherPromotion : productPromotions) {
                if (otherPromotion.getId().equals(promotion.getId())) {
                    continue;
                }
                if (!(promotion.getBeginTime().after(otherPromotion.getEndTime()) || promotion.getEndTime().before(otherPromotion.getBeginTime()))) {
                    return true;
                }
            }
        }
        return false;
    }

    @Transactional
    @Override
    public Result savePromotionGroup(PromotionGroup promotionGroup) {
        //判断商品参加的活动时间是否重叠
        if (promotionGroup.getStatus() == 1 && isProductPromotionTimeConflict(promotionGroup)) {
            return Result.error("该商品已参与的其他活动与当前活动时间重叠，无法上架!");
        }

        //保存拼团商品
        promotionGroupMapper.insert(promotionGroup);
        //保存拼团sku列表
        if (promotionGroup.getGroupSkus() != null) {
            for (PromotionGroupSku groupSku : promotionGroup.getGroupSkus()) {
                groupSku.setGroupId(promotionGroup.getId());
                groupSku.setStockLeft(groupSku.getStockInit());
                promotionGroupSkuMapper.insert(groupSku);
            }
        }
        return Result.ok("添加成功!");
    }

    @Transactional
    @Override
    public Result updatePromotionGroup(PromotionGroup promotionGroup) {
        //判断商品参加的活动时间是否重叠
        if (promotionGroup.getStatus() == 1 && isProductPromotionTimeConflict(promotionGroup)) {
            return Result.error("该商品已参与的其他活动与当前活动时间重叠，无法上架!");
        }
        //更新拼团商品
        promotionGroupMapper.updateById(promotionGroup);
        //更新拼团sku列表
        if (promotionGroup.getGroupSkus() != null) {
            for (PromotionGroupSku groupSku : promotionGroup.getGroupSkus()) {
                if (groupSku.getId() == null) {
                    groupSku.setGroupId(promotionGroup.getId());
                    groupSku.setStockLeft(groupSku.getStockInit());
                    promotionGroupSkuMapper.insert(groupSku);
                } else {
                    Integer addStock;
                    PromotionGroupSku oldGroupSku = promotionGroupSkuMapper.selectById(groupSku.getId());
                    if ((addStock = groupSku.getStockInit() - oldGroupSku.getStockInit()) != 0) {
                        groupSku.setStockLeft(oldGroupSku.getStockLeft() + addStock);
                    } else {
                        groupSku.setStockLeft(null);
                    }
                    promotionGroupSkuMapper.updateById(groupSku);
                }
            }
        }
        return Result.ok("编辑成功!");
    }

    @Override
    public Result changeStatus(Long id, Integer status) {
        if (status == 1) {
            PromotionGroup promotionGroup = promotionGroupMapper.selectById(id);
            if (promotionGroup != null && isProductPromotionTimeConflict(promotionGroup)) {
                return Result.error("该商品已参与的其他活动与当前活动时间重叠，无法上架!");
            }
        }
        PromotionGroup flashProduct = new PromotionGroup();
        flashProduct.setId(id);
        flashProduct.setStatus(status);
        promotionGroupMapper.updateById(flashProduct);
        return Result.ok("操作成功!");
    }

    @Override
    public PromotionGroup getPromotionGroupDetail(Long id) {
        PromotionGroup group = promotionGroupMapper.selectById(id);
        if (group != null) {
            List<PromotionGroupSku> groupSkus = promotionGroupSkuMapper.selectList(new QueryWrapper<PromotionGroupSku>().lambda().eq(PromotionGroupSku::getGroupId, id));
            group.setGroupSkus(groupSkus);
        }
        return group;
    }

    @Override
    public Result<?> selectNojoinProducts(Long id, Long productId) {
        PromotionGroupNoJoin promotionGroupNoJoin = promotionGroupMapper.selectPromotionGroupNoJoin(id, productId);
        if (promotionGroupNoJoin == null) {
            return Result.ok();
        }
        List<PromotionGroupNojoinSku> skuList = promotionGroupMapper.selectPromotionGroupSkuNojoin(id, productId);
        promotionGroupNoJoin.setSkuList(skuList);
        return Result.ok(promotionGroupNoJoin);
    }

    @Override
    public Result<?> selectProduct(Long promotionId) {
        PromotionGroupNoJoin promotionGroupNoJoin = promotionGroupMapper.selectPromotionGroupNoJoinProduct(promotionId);
        return Result.ok(promotionGroupNoJoin);
    }

    @Override
    public Result changeGroupSkuStock(Long groupSkuId, Integer changeNum) {
        int flag = promotionGroupSkuMapper.changeGroupSkuStock(groupSkuId, changeNum);
        if (flag == 0) {
            return Result.error(ProductResultCode.STOCK_NOT_ENOUGH, "库存不足");
        }
        return Result.ok();
    }
}
